package net.cyue.nest.nestjava.core.injector;

import net.cyue.nest.nestjava.common.data.InjectableMetaType;
import net.cyue.nest.nestjava.common.data.MetaType;
import net.cyue.nest.nestjava.common.data.module.ControllerMeaType;
import net.cyue.nest.nestjava.common.data.module.ProviderMetaType;

import java.util.HashMap;
import java.util.Map;

public class ModuleData {
  private final MetaType metaType;
  // private final Set<Module> importSet = new HashSet<>();
  // private final Set<MetaType> exportSet = new HashSet<>();
  private final Map<MetaType, InstanceWrapper> injectableMap = new HashMap<>();
  private final Map<MetaType, InstanceWrapper> controllerMap = new HashMap<>();
  private final Map<MetaType, InstanceWrapper> providerMap = new HashMap<>();

  public ModuleData(MetaType metaType) {
    this.metaType = metaType;
  }

  public String getName() {
    return this.metaType.getName();
  }
  public MetaType getMetaType() {
    return this.metaType;
  }


  public InstanceWrapper getControllerWrapper(MetaType metaType) {
    return this.controllerMap.get(metaType);
  }
  public InstanceWrapper[] getControllerInstanceWrappers() {
    return this.controllerMap.values().toArray(new InstanceWrapper[0]);
  }

  public Object getInjectableInstance(MetaType type) {
    InstanceWrapper wrapper = this.injectableMap.get(type);
    if (wrapper == null) {
      return null;
    }
    return wrapper.getInstance();
  }
  public Object[] getInjectableInstances() {
    InstanceWrapper[] wrapperArray = this.injectableMap.values().toArray(new InstanceWrapper[0]);
    Object[] instanceArray = new Object[wrapperArray.length];
    for (int i = 0; i < instanceArray.length; i++) {
      instanceArray[i] = wrapperArray[i].getInstance();
    }
    return instanceArray;
  }
  public InstanceWrapper[] getInjectableInstanceWrappers(MetaType type) {
    return this.injectableMap.values().toArray(new InstanceWrapper[0]);
  }

  public Object getProviderInstance(MetaType type) {
    InstanceWrapper wrapper = this.providerMap.get(type);
    if (wrapper == null) {
      return null;
    }
    return wrapper.getInstance();
  }
  public Object[] getProviderInstances() {
    InstanceWrapper[] wrapperArray = this.providerMap.values().toArray(new InstanceWrapper[0]);
    Object[] instanceArray = new Object[wrapperArray.length];
    for (int i = 0; i < instanceArray.length; i++) {
      instanceArray[i] = wrapperArray[i].getInstance();
    }
    return instanceArray;
  }
  public InstanceWrapper[] getProviderInstanceWrappers() {
    return this.providerMap.values().toArray(new InstanceWrapper[0]);
  }

  public Object getControllerInstance(MetaType type) {
    InstanceWrapper wrapper = this.controllerMap.get(type);
    if (wrapper == null) {
      return null;
    }
    return wrapper.getInstance();
  }
  public Object[] getControllerInstances() {
    final var wrappers = this.controllerMap.values().toArray(new InstanceWrapper[0]);
    final var instances = new Object[wrappers.length];
    for (int i = 0; i < wrappers.length; i++) {
      instances[i] = wrappers[i].getInstance();
    }
    return instances;
  }

//  public void addImport(Module module) {
//    this.importSet.add(module);
//  }

//  public void addExportedProvider(Provider provider) {
//    if (this.providerMap.containsKey(provider.metaType)) {
//      this.exportSet.add(provider.metaType);
//    } else {
//      throw new RuntimeException("Module 导出不存在的 Provider");
//    }
//  }

  public void addInjectable(InjectableMetaType injectableMetaType) {
    InstanceWrapper wrapper = this.injectableMap.get(injectableMetaType);
    if (wrapper == null) {
      wrapper = Injector.INSTANCE_REGISTRY.registerInstance(injectableMetaType, this);
      this.injectableMap.put(injectableMetaType, wrapper);
    }
  }

  public void addProvider(ProviderMetaType providerMetaType) {
    InstanceWrapper wrapper = this.providerMap.get(providerMetaType);
    if (wrapper == null) {
      wrapper = Injector.INSTANCE_REGISTRY.registerInstance(providerMetaType, this);
      this.providerMap.put(providerMetaType, wrapper);
    }
  }

  public void addController(ControllerMeaType controllerMeaType) {
    InstanceWrapper wrapper = this.controllerMap.get(controllerMeaType);
    if (wrapper == null) {
      wrapper = Injector.INSTANCE_REGISTRY.registerInstance(controllerMeaType, this);
      this.controllerMap.put(controllerMeaType, wrapper);
    }
  }

}


